using System;
using System.IO;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.CommandBars;
using System.Resources;
using System.Reflection;
using System.Globalization;
using System.Collections.Generic;
using System.Windows.Forms;

namespace ICeFramework.Addin
{
    public delegate void MenuClickHandler(object sender, MenuClickEventArgs e);

    public class MenuManager
    {
        private DTE2 application;
        private List<CommandBarEvents> menuItemHandlerList = new List<CommandBarEvents>();
        private Dictionary<string, CommandBase> cmdList = new Dictionary<string, CommandBase>();

        public event MenuClickHandler MenuClick;

        public MenuManager(DTE2 application)
        {
            this.application = application;
        }

        public CommandBarPopup CreatePopupMenu(string commandBarName, string menuName)
        {
            if (GetCommandBar(commandBarName) != null)
            {
                CommandBarPopup menu = GetCommandBar(commandBarName).Controls.Add(MsoControlType.msoControlPopup, Missing.Value, Missing.Value, 1, true) as CommandBarPopup;
                menu.Caption = menuName;
                menu.TooltipText = "";
                return menu;
            }
            else
            {
                return null;
            }
        }

        public CommandBarPopup CreatePopupMenu(CommandBarPopup popupMenu, string subPopupMenuName, int position)
        {
            CommandBarPopup menu = (CommandBarPopup)popupMenu.Controls.Add(MsoControlType.msoControlPopup, 1, "", position, true);
            menu.Caption = subPopupMenuName;
            menu.TooltipText = "";
            return menu;
        }

        public CommandBar GetCommandBar(string commandBarName)
        {
            try
            {
                return ((CommandBars)application.DTE.CommandBars)[commandBarName];
            }
            catch
            {
                return null;
            }
        }

        public void AddCommandMenu(CommandBarPopup popupMenu, string name, string caption, string tooltipText, DTE2 application, int position, bool beginGroup)
        {
            if (popupMenu != null)
            {
                CommandBase command = CommandFactory.Create(name, caption, tooltipText, application);
                CommandBarControl menuItem = AddMenuItem(popupMenu, command, position);
                menuItem.BeginGroup = beginGroup;
                AddClickEventHandler(menuItem);
                AddCommandToList(command);
            }
        }

        public void AddCommandMenu(CommandBar popupMenu, string name, string caption, string tooltipText, DTE2 application, int position, bool beginGroup)
        {
            if (popupMenu != null)
            {
                CommandBase command = CommandFactory.Create(name, caption, tooltipText, application);
                CommandBarControl menuItem = AddMenuItem(popupMenu, command, position);
                menuItem.BeginGroup = beginGroup;
                AddClickEventHandler(menuItem);

                AddCommandToList(command);
            }
        }

        private CommandBarControl AddMenuItem(CommandBarPopup menu, CommandBase cmd, int position)
        {
            CommandBarControl menuItem = menu.Controls.Add(MsoControlType.msoControlButton, 1, "", position, true);            
            menuItem.Tag = cmd.Id.ToString();
            menuItem.Caption = cmd.Caption;
            menuItem.TooltipText = cmd.TooltipText;
            return menuItem;
        }

        private CommandBarControl AddMenuItem(CommandBar menu, CommandBase cmd, int position)
        {
            CommandBarControl menuItem = menu.Controls.Add(MsoControlType.msoControlButton, 1, "", position, true);
            menuItem.Tag = cmd.Id.ToString();
            menuItem.Caption = cmd.Caption;
            menuItem.TooltipText = cmd.TooltipText;
            return menuItem;
        }

        private void AddClickEventHandler(CommandBarControl menuItem)
        {
            CommandBarEvents menuItemHandler = (EnvDTE.CommandBarEvents)application.DTE.Events.get_CommandBarEvents(menuItem);
            menuItemHandler.Click += new _dispCommandBarControlEvents_ClickEventHandler(MenuItem_Click);
            menuItemHandlerList.Add(menuItemHandler);
        }

        private void AddCommandToList(CommandBase cmd)
        {
            if (!cmdList.ContainsKey(cmd.Id.ToString()))
            {
                cmdList.Add(cmd.Id.ToString(), cmd);
            }
        }

        private void MenuItem_Click(object commandBarControl, ref bool handled, ref bool cancelDefault)
        {
            try
            {
                // We perform the command only if we found the command corresponding to the menu item clicked
                CommandBarControl menuItem = (CommandBarControl)commandBarControl;
                if (cmdList.ContainsKey(menuItem.Tag))
                {
                    OnMenuClick(cmdList[menuItem.Tag]);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Add-in");
            }
        }

        private void OnMenuClick(CommandBase command)
        {
            if (MenuClick != null)
            {
                MenuClick(this, new MenuClickEventArgs(command));
            }
        }
    }

    public class MenuClickEventArgs
    {
        private CommandBase _command;
        #region public CommandBase Command
        /// <summary>
        /// Gets the Command of the MenuClickEventArgs
        /// </summary>
        /// <value></value>
        public CommandBase Command
        {
            get { return _command; }
        }
        #endregion

        #region public MenuClickEventArgs(CommandBase command)
        /// <summary>
        /// Initializes a new instance of the <b>MenuClickEventArgs</b> class.
        /// </summary>
        /// <param name="command"></param>
        public MenuClickEventArgs(CommandBase command)
        {
            _command = command;
        }
        #endregion
    }
}
